
#include <xgba_p.h>
#include <xgba.h>
#include <xgba_vram.h>
#if defined(_SIMD_)
#include <xmmintrin.h>
#endif
#include <string.h>

INLINE tile_render_line_ex(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int isTile256,int map_n){
    hofs &= 0x1ff;
    vofs &= 0x1ff;
    line += vofs;       //y偏移
    while(line>=tile_h){
        //会从0重复
        line = line - tile_h;
    }
    int tileY = line>>3;    // /=8
    int tile_my = line & 7;
    int map_offset = tileY * (tile_w>>3); //tile_w为256
    uint16_t *map_row = map + map_offset;
    uint32_t *pal_data = gba->tilePal;
    int x=0;
    /*
    hofs 现在利用pixels + offset偏移
    */
    #define PIXEL_BUF 1
    #if PIXEL_BUF
    uint32_t pixel_buf[0x110];
    #endif

    for(x=0;x<=256;x+=8,map_row++){
        int tid = map_row[0]&0x3ff;
        int hflip = (map_row[0]>>10) & 1;
        int vflip = (map_row[0]>>11) & 1;
        int pal_num = (map_row[0]>>12);
        map_row = map + map_offset; //hofs :x偏移
        map_offset ++;

        int yoff = ((vflip<<3)-vflip);     //如果vflip 为0,则yoff为0,如果vflip不为0,则等于7
        yoff |= ((tile_my&~yoff)<<(~vflip&1));   //如果yoff为0,则tile_my<<1,否则0<<0

        /*
        水平翻转
        xadd 取值为-1，则为翻转, 为1,则不翻转。
        p 取值为，翻转则pixels+7. 不翻转则为pixels+0

        如果tile数据不为0时，则mask为-1,则颜色为
            (pal&mask) | (p[0]&~mask)
        为0时，mask=0
            (pal&mask) | (p[0]&~mask)

        */
        int xadd = (-hflip ^ hflip) + 1;
        #if PIXEL_BUF
        uint32_t *p = pixel_buf + (hflip<<3) - hflip + x;  //+7或+0
        #else
        uint32_t *p = pixels + (hflip<<3) - hflip + x;  //+7或+0
        #endif

        int td = 0; /*tile 数据*/
        uint32_t color;
        int32_t mask = 0;

        if(!isTile256){
            //16色模式
            //获得tile数据,32位为8个4bit的数据
            uint8_t *tile_data = tile + tid*0x20;
            tile_data += (yoff - tile_my) * 4;
            uint32_t*pal = pal_data + pal_num * 0x10;
            uint32_t tile_data32 = *(uint32_t*)tile_data;
            #if PIXEL_BUF
            td = (tile_data32>>0x00)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x04)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x0c)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x14)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x1c)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color;
            #else
            td = (tile_data32>>0x00)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x04)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x0c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x14)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x1c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask;p[0]=color;
            #endif
        }
        else{
            //256色模式
            uint8_t *tile_data = tile + tid*0x40;
            tile_data += (yoff - tile_my) * 8;
            uint32_t*pal = pal_data;
            uint32_t tile_data32 = ((uint32_t*)tile_data)[0];
            td = (tile_data32>>0x00)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            tile_data32 = ((uint32_t*)tile_data)[1];
            td = (tile_data32>>0x00)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color;
        }
    }
    #if PIXEL_BUF
    int i;
    int d = hofs;
    for(i=0;i<240;i++){
        while(d>=256){
            d -= 256;
        }
        if(pixel_buf[d]){
            pixels[i] = pixel_buf[d];
        }
        d += 1;
    }
    #endif
    return 0;
}


INLINE tile_render_line_ex_blend(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int isTile256,int map_num){
    hofs &= 0x1ff;
    vofs &= 0x1ff;
    line += vofs;       //y偏移
    while(line>=tile_h){
        //会从0重复
        line = line - tile_h;
    }
    int tileY = line>>3;    // /=8
    int tile_my = line & 7;
    int map_offset = tileY * (tile_w>>3); //tile_w为256
    uint16_t *map_row = map + map_offset;
    uint32_t *pal_data = gba->tilePal;
    int x=0;
    /*
    hofs 现在利用pixels + offset偏移
    */
    #define PIXEL_BUF 1
    #if PIXEL_BUF
    uint32_t pixel_buf[0x110];
    #endif

    for(x=0;x<=256;x+=8,map_row++){
        int tid = map_row[0]&0x3ff;
        int hflip = (map_row[0]>>10) & 1;
        int vflip = (map_row[0]>>11) & 1;
        int pal_num = (map_row[0]>>12);
        map_row = map + map_offset; //hofs :x偏移
        map_offset ++;

        int yoff = ((vflip<<3)-vflip);     //如果vflip 为0,则yoff为0,如果vflip不为0,则等于7
        yoff |= ((tile_my&~yoff)<<(~vflip&1));   //如果yoff为0,则tile_my<<1,否则0<<0

        /*
        水平翻转
        xadd 取值为-1，则为翻转, 为1,则不翻转。
        p 取值为，翻转则pixels+7. 不翻转则为pixels+0

        如果tile数据不为0时，则mask为-1,则颜色为
            (pal&mask) | (p[0]&~mask)
        为0时，mask=0
            (pal&mask) | (p[0]&~mask)

        */
        int xadd = (-hflip ^ hflip) + 1;
        #if PIXEL_BUF
        uint32_t *p = pixel_buf + (hflip<<3) - hflip + x;  //+7或+0
        #else
        uint32_t *p = pixels + (hflip<<3) - hflip + x;  //+7或+0
        #endif

        int td = 0; /*tile 数据*/
        uint32_t color;
        int32_t mask = 0;

        if(!isTile256){
            //16色模式
            //获得tile数据,32位为8个4bit的数据
            uint8_t *tile_data = tile + tid*0x20;
            tile_data += (yoff - tile_my) * 4;
            uint32_t*pal = pal_data + pal_num * 0x10;
            uint32_t tile_data32 = *(uint32_t*)tile_data;
            #if PIXEL_BUF
            td = (tile_data32>>0x00)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x04)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x0c)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x14)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x1c)&0xf;mask = (~td+1)|td;mask>>=31; color=pal[td];color &=mask; p[0]=color;
            #else
            td = (tile_data32>>0x00)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x04)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x0c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x14)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x1c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask;p[0]=color;
            #endif
        }
        else{
            //256色模式
            uint8_t *tile_data = tile + tid*0x40;
            tile_data += (yoff - tile_my) * 8;
            uint32_t*pal = pal_data;
            uint32_t tile_data32 = ((uint32_t*)tile_data)[0];
            td = (tile_data32>>0x00)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            tile_data32 = ((uint32_t*)tile_data)[1];
            td = (tile_data32>>0x00)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x08)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x10)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color; p += xadd;//下一个颜色
            td = (tile_data32>>0x18)&0xff;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=p[0]&~mask; p[0]=color;
        }
    }
    #if PIXEL_BUF
    int i;
    int d = hofs;
    int eva = gba->io[0x52]&0x1f;
    int evb = gba->io[0x53]&0x1f;
    int evy = gba->io[0x54]&0x1f;
    if(eva>0x10)eva = 0x10;
    if(evb>0x10)evb = 0x10;
    if(evy>0x10)evy = 0x10;
    //8位是小数
    eva *= 0x10;
    evb *= 0x10;
    evy *= 0x10;
    for(i=0;i<240;i++){
        while(d>=256){
            d -= 256;
        }
        if(pixel_buf[d]){
            //混合
            int r2 =  (pixels[i]>>0x00)&0xff;
            int g2 =  (pixels[i]>>0x08)&0xff;
            int b2 =  (pixels[i]>>0x10)&0xff;
            //第一目标像素
            //第一目标像素紧随第二目标像素之后
            int r = (pixel_buf[d]>>0x00)&0xff;
            int g = (pixel_buf[d]>>0x08)&0xff;
            int b = (pixel_buf[d]>>0x10)&0xff;
            //pixels[i] = pixel_buf[d];
            r = r*eva + r2 * evb;
            g = g*eva + g2 * evb;
            b = b*eva + b2 * evb;
            r >>= 8;
            g >>= 8;
            b >>= 8;
            if(r>=0x100)r = 0xff;
            if(g>=0x100)g = 0xff;
            if(b>=0x100)b = 0xff;
            pixels[i] = (r<<0)|(g<<8)|(b<<16);
        }
        d += 1;
    }
    #endif
    return 0;
}

int tile4_render_line(xgba_t*gba,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w){
    int tileY = line>>3;    //一个tile高8像素
    int tile_my = line & 7; //在tile偏移y
    uint16_t *map_row = map + tileY * tile_w;
    uint32_t *pal_data = gba->tilePal;
    int x=0;
    #if defined(_SIMD_)
    //SIMD加速,需要定义一个索引色缓存
    int32_t color_index[1024];
    int32_t pal_buf[512];
    #endif

    for(x=0;x<256/8;x++){
        int tid = map_row[0]&0x3ff;
        int hflip = (map_row[0]>>10) & 1;
        int vflip = (map_row[0]>>11) & 1;
        int pal_num = (map_row[0]>>12);
        uint32_t*pal = pal_data + pal_num * 0x10;
        //获得tile数据,32位为8个4bit的数据
        uint8_t *tile_data = tile + tid*0x20;
        #if 0
        if(!vflip)
            tile_data += tile_my * 4;       //获得目标行
        else
            tile_data += (7-tile_my)*4;     //垂直翻转
        #else
        int yoff = -((vflip<<8)-1);
        tile_data += (tile_my + yoff) * 4;
        #endif

        /*
        水平翻转
        xadd 取值为-1，则为翻转, 为1,则不翻转。
        p 取值为，翻转则pixels+7. 不翻转则为pixels+0

        如果tile数据不为0时，则mask为-1,则颜色为
            (pal&mask) | (p[0]&~mask)
        为0时，mask=0
            (pal&mask) | (p[0]&~mask)

        */
        int xadd = (-hflip ^ hflip) + 1;
        uint32_t *p = pixels + (hflip<<3) - hflip + x*8;  //+7或+0
        uint32_t tile_data32 = *(uint32_t*)tile_data;
        int td = 0; /*tile 数据*/
        uint32_t color;
        int32_t mask = 0;

        #if defined(_SIMD_)&&0
        //由于读写内存次数多,效率会变低
        pal_buf[x] = pal_num;
        uint32_t *color_i = color_index + (hflip<<3) - hflip + x*8;  //+7或+0
        *color_i = (tile_data32>>0x00)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x04)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x08)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x0c)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x10)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x14)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x18)&0xf;color_i += xadd;
        *color_i = (tile_data32>>0x1c)&0xf;
        color_i = color_index + x*8;
        __v4su *color_mask = (__v4su *)&color_i[0];
        __v4su color_1,color_2;
        color_1[0] = pal[color_i[0]];
        color_1[1] = pal[color_i[1]];
        color_1[2] = pal[color_i[2]];
        color_1[3] = pal[color_i[3]];
        color_2[0] = pal[color_i[4]];
        color_2[1] = pal[color_i[5]];
        color_2[2] = pal[color_i[6]];
        color_2[3] = pal[color_i[7]];

        color_mask[0] = -color_mask[0]|color_mask[0];
        color_mask[0] =  color_mask[0]>>31;
        color_mask[1] = -color_mask[1]|color_mask[1];
        color_mask[1] =  color_mask[1]>>31;
        p = pixels + x*8;  //+7或+0
        *(__v4su*)p = (*(__v4su*)p&~color_mask[0])|(color_1&color_mask[0]);
        p += 4;
        *(__v4su*)p = (*(__v4su*)p&~color_mask[1])|(color_2&color_mask[1]);


        #else
        #if 0
        td = (tile_data32>>0x00)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x04)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x08)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x0c)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x10)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x14)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x18)&0xf;color = td?pal[td]:p[0]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x1c)&0xf;color = td?pal[td]:p[0]; p[0]=color;
        #else
        td = (tile_data32>>0x00)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x04)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x08)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x0c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x10)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x14)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x18)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color; p += xadd;//下一个颜色
        td = (tile_data32>>0x1c)&0xf;mask = (~td+1)|td;mask>>=31;color=mask&pal[td]; color|=~mask&pal[td]; p[0]=color;
        #endif
        #endif

        map_row++;
    }

    #if defined(_SIMD_)&&0
    //先处理颜色mask
    uint32_t pixel_colors[512];
    for(x=0;x<256;x+=4){
        __v4si *colors = ((__v4si*)&color_index[x]);
        pixel_colors[x + 0] = pal_data[pal_buf[x+0]*0x10+colors[0][0]];
        pixel_colors[x + 1] = pal_data[pal_buf[x+1]*0x10+colors[0][1]];
        pixel_colors[x + 2] = pal_data[pal_buf[x+2]*0x10+colors[0][2]];
        pixel_colors[x + 3] = pal_data[pal_buf[x+3]*0x10+colors[0][3]];
        *colors = (-*colors)|*colors;
        *colors = *colors>>31;
    }
    for(x=0;x<256;x+=4){
        __v4su *mask = ((__v4su*)&color_index[x]);
        __v4su *pixel_v4 = ((__v4su*)&pixels[x]);
        __v4su nmask = ~mask[0];
        __v4su *pal_pixel = ((__v4su*)&pixel_colors[x]);
        *pixel_v4 = (pixel_v4[0]&nmask)|(pal_pixel[0]&mask[0]);
    }

    #endif

    return pixels[2];
}

typedef struct{
    int         num;
    uint32_t    *pixel;
}vram_pixel_layer_t;

static int pixel_blend(xgba_t*gba,uint32_t*screen_line,vram_pixel_layer_t*layer){
    int layer_num = 7;
    int pixel_idx = 0;
    uint8_t _1st = gba->io[0x50]&0x3f;
    uint8_t _2nd = gba->io[0x51]&0x3f;
    int eva = gba->io[0x52]&0x1f;
    int evb = gba->io[0x53]&0x1f;
    int evy = gba->io[0x54]&0x1f;
    if(eva>0x10)eva = 0x10;
    if(evb>0x10)evb = 0x10;
    if(evy>0x10)evy = 0x10;
    //8位是小数
    eva *= 0x10;
    evb *= 0x10;
    evy *= 0x10;
    for(pixel_idx=0;pixel_idx<240;pixel_idx++){
        uint32_t _1st_pixel = 0;
        int isblend = 0;
        for(layer_num=7;layer_num>=0;layer_num--){
            /*遇到为空的像素才穿透找上一层函数*/
            uint32_t p = layer[layer_num].pixel[pixel_idx];
            if(p){
                //非空颜色
                if(isblend&&(_2nd&(1<<layer[layer_num].num))){
                    //_2nd混合
                    int r2 =  (p>>0x00)&0xff;
                    int g2 =  (p>>0x08)&0xff;
                    int b2 =  (p>>0x10)&0xff;
                    //第一目标像素
                    //第一目标像素紧随第二目标像素之后
                    int r = (_1st_pixel>>0x00)&0xff;
                    int g = (_1st_pixel>>0x08)&0xff;
                    int b = (_1st_pixel>>0x10)&0xff;
                    //pixels[i] = pixel_buf[d];
                    r = r*eva + r2 * evb;
                    g = g*eva + g2 * evb;
                    b = b*eva + b2 * evb;
                    r >>= 8;
                    g >>= 8;
                    b >>= 8;
                    if(r>=0x100)r = 0xff;
                    if(g>=0x100)g = 0xff;
                    if(b>=0x100)b = 0xff;
                    screen_line[pixel_idx] = (r<<0)|(g<<8)|(b<<16);
                }
                else if(_1st&(1<<layer[layer_num].num)){
                    //_1st混合
                    isblend = 1;
                    _1st_pixel = p;
                }
                else{
                    //非混合图层
                    screen_line[pixel_idx] = p;
                    break;
                }
            }
        }
    }
    return 0;
}

struct display_func_t{
    int bg0:1;
    int bg1:1;
    int bg2:1;
    int bg4:1;
    int bg0_pri:2;
    int bg1_pri:2;
    int bg2_pri:2;
    int bg4_pri:2;
};

static int tile_render_line16(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int map_num){
    return tile_render_line_ex(gba,hofs,vofs,pixels,map,tile,line,tile_w,tile_h,0,map_num);
}

static int tile_render_line256(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int map_num){
    return tile_render_line_ex(gba,hofs,vofs,pixels,map,tile,line,tile_w,tile_h,1,map_num);
}

static int tile_render_line16_blend(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int map_num){
    return tile_render_line_ex_blend(gba,hofs,vofs,pixels,map,tile,line,tile_w,tile_h,0,map_num);
}

static int tile_render_line256_blend(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int map_num){
    return tile_render_line_ex_blend(gba,hofs,vofs,pixels,map,tile,line,tile_w,tile_h,1,map_num);
}

typedef int (*tile_render_line_func_t)(xgba_t*gba,uint32_t hofs,uint32_t vofs,uint32_t *pixels,uint16_t *map,uint8_t*tile,int line,int tile_w,int tile_h,int map_num);

static tile_render_line_func_t render_line[2] = {
    tile_render_line16,
    tile_render_line256
};

static tile_render_line_func_t render_line_blend[2] = {
    tile_render_line16_blend,
    tile_render_line256_blend,
};

#define RENDER_LAYER(n,shift_l,_screen_line,render_line) \
if(*(uint16_t*)(&gba->io[0])&(1<<(shift_l))){ \
    uint16_t *map##n =       (uint16_t*)(gba->vram + (cnt##n->screen_base* (1024*2/*2 KBytes*/) )); \
    uint8_t  *tile##n##_data = (uint8_t*) (gba->vram + (cnt##n->char_base * (1024*16/*16 KBytes*/))); \
    uint16_t hofs = *(uint16_t*)(&gba->io[0x10+n*4]); \
    uint16_t vofs = *(uint16_t*)(&gba->io[0x12+n*4]); \
    render_line[cnt##n->color256](gba,hofs,vofs,_screen_line,map##n,tile##n##_data,gba->screen_line,256<<(cnt##n->screen_size&1),256<<((cnt##n->screen_size>>1)&1),n); \
}

    // if(((gba->io[0x50]>>6)==0b01)) \
    //     if(gba->io[0x51]&(1<<n))render_line_ptr = render_line_blend;/*混合模式,该图层为第一像素*/\
    // else \
    //     render_line_ptr = render_line;/*关闭混合像素*/\

const static int oam_size[] = {
    0x0808,
    0x1010,
    0x2020,
    0x4040,
    0x0810,
    0x0820,
    0x1020,
    0x2040,
    0x1008,
    0x2008,
    0x2010,
    0x4020,
    0,
    0,
    0,
    0,
};

static int oam_render_norotate(xgba_t*gba,uint32_t *pixel,xgba_obj_att0_t *att0,xgba_obj_att1_t *att1,xgba_obj_att2_t *att2,int x,int y,int w,int h){
    int x2 = x + w;
    int y2 = y + h;
    if(att1->vflip){
        //垂直翻转,如果翻转时,从最高的地方开始复制
        y2 = y2 - gba->screen_line;
    }
    else{
        //没有翻转,从低0行开始
        y2 = gba->screen_line-y;     //偏移多少行
    }
    int tileY = y2/8;          //偏移Y个tile
    int offY = y2&7;            //tile偏移行数
    uint16_t ch = att2->char_num;
    uint32_t *pal = gba->tilePal+0x100;
    if(!att0->color256){
        pal += 0x10*att2->pal;
    }
    if(DISPCNT->obj_char_vram_map){
        //一维显示
        ch += tileY * (w/8);
    }
    else{
        //二维显示
        ch += tileY * 0x20;
    }
    uint8_t *tile_data = gba->vram + 0x10000;
    tile_data += ch * (0x20<<att0->color256);   //如果是256色,则0x40
    tile_data += offY * (4<<att0->color256);    //如果是256色,则tile一行为8个字节
    int hadd = 1;   //水平
    if(att1->hflip){
        //水平翻转
        hadd = -1;
        x = x2-1;
    }
    while(w>0){
        uint32_t td;
        td = *(uint32_t*)tile_data;
        int palId = 0;
        int32_t mask = 0;
        uint32_t color = 0;
        if(!att0->color256){
            palId = (td>>0x00)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x04)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x08)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x0c)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x10)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x14)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x18)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x1c)&0xf;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            tile_data += 0x20;  //下一个tile
        }
        else{
            palId = (td>>0x00)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x08)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x10)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x18)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            td = ((uint32_t*)tile_data)[1];
            palId = (td>>0x00)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x08)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x10)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            palId = (td>>0x18)&0xff;mask = -palId; mask>>=31; color=mask&pal[palId]; color |= ~mask&pixel[x]; pixel[x] = color; x += hadd;
            tile_data += 0x40;  //下一个tile
        }

        w -= 8;
    }
}

static int oam_render_rotate(xgba_t*gba,uint32_t *pixel,xgba_obj_att0_t *att0,xgba_obj_att1_t *att1,xgba_obj_att2_t *att2,int x,int y,int w,int h){
    //获得中心点
    int mid_x;
    int mid_y;
    int off_x;
    int x2 = x + w;
    int y2 = y + h;
    int param = ((*(uint16_t*)att1)>>9) & 0x1f;
    int dx =  *(uint16_t*)(gba->oam + 0x8 * (param * 4 + 0) + 6);
    int dmx = *(uint16_t*)(gba->oam + 0x8 * (param * 4 + 1) + 6);
    int dy =  *(uint16_t*)(gba->oam + 0x8 * (param * 4 + 2) + 6);
    int dmy = *(uint16_t*)(gba->oam + 0x8 * (param * 4 + 3) + 6);
    dx |= (dx&0x8000)*0x1FFFF;
    dy |= (dy&0x8000)*0x1FFFF;
    dmx |= (dmx&0x8000)*0x1FFFF;
    dmy |= (dmy&0x8000)*0x1FFFF;

    // dx = 0x100;
    // dmx = 0x00;
    // dy = 0x00;
    // dmy = 0x100;


    int off_y = (gba->screen_line-att0->y);
    int tw = w>>att0->dsize;
    int th = h>>att0->dsize;
    uint32_t *pal = gba->tilePal + 0x100 + (att2->pal * (~att0->color256&1) * 0x10);
    mid_x = w>>1;
    mid_y = h>>1;
    for(off_x=0;off_x<w;off_x++){
        int X = off_x - mid_x ;
        int Y = off_y - mid_y ;
        int tile_x = mid_x;         //基础位置
        int tile_off_x = 0;
        tile_off_x += ((X *dx));     //同一行向x偏移量
        tile_off_x += ((Y*dmx));     //下一行向x偏移量
        tile_x += (tile_off_x>>8);   //需要合并再位移
        int tile_y = mid_y;         //基础位置
        int tile_off_y = 0;
        tile_off_y += ((X *dy));     //同一行向y偏移量
        tile_off_y += (Y*dmy);       //下一行向y偏移量
        tile_y += tile_off_y>>8;       //需要合并再位移
        if(
            !(tile_x>tw||tile_x<0||tile_y>th||tile_y<0)
        ){
            int TX = tile_x >>3;    //向左偏移图块
            int TY = tile_y >>3;    //向下偏移图块
            int TID = att2->char_num;
            TID += TX;
            if(DISPCNT->obj_char_vram_map){
                //一维显示
                TID += tw * TY; //一维数组
            }
            else{
                //二维显示
                TID += 0x20 * TY;   //二维数组
            }
            uint8_t * vram = (gba->vram + 0x10000) + TID * (0x20<<att0->color256);
            vram += (tile_y&7)*(4<<att0->color256);     //tile偏移y
            vram += (tile_x&7)>>(1-att0->color256);     //tile偏移x
            uint8_t td = vram[0];
            td >>= (~att0->color256&tile_x&1)<<2;      //如果不是256色,并且tile_x偏移1。则向左位移4
            td &= 0xff>>((1-att0->color256)*4);        //如果是16色,则位移4
            if(td){
                pixel[off_x+att1->x] = pal[td];
            }
        }
    }
}

static int oam_render(xgba_t*gba,uint32_t *pixel,uint8_t *oam_list,int idx){
    uint8_t *oam = oam_list + 1;
    uint8_t num = oam_list[0];
    int i;
    for(i=num-1;i>=0;i--){
        xgba_obj_att0_t *att0 = (xgba_obj_att0_t*)(gba->oam+oam[i]*8+0);
        xgba_obj_att1_t *att1 = (xgba_obj_att1_t*)(gba->oam+oam[i]*8+2);
        xgba_obj_att2_t *att2 = (xgba_obj_att2_t*)(gba->oam+oam[i]*8+4);
        uint16_t size = ((att0->shape<<2) | att1->size);
        size = oam_size[size];
        int w = size & 0xff;
        int h = (size>>8)&0xff;
        int x = att1->x;
        int y = att0->y;
        if(att0->r_s_flg&&att0->dsize){
            w <<= 1;
            h <<= 1;
        }
        int x2 = x + w;
        int y2 = y + h;
        if(y<=gba->screen_line&&gba->screen_line<y2){
            if(!att0->r_s_flg){
                oam_render_norotate(gba,pixel,att0,att1,att2,x,y,w,h);
            }
            else{
                oam_render_rotate(gba,pixel,att0,att1,att2,x,y,w,h);
            }
        }
    }
}

#define DOBJ3 oam_render(gba,screen_line,gba->obj_render[3],3);
#define DOBJ2 oam_render(gba,screen_line,gba->obj_render[2],2);
#define DOBJ1 oam_render(gba,screen_line,gba->obj_render[1],1);
#define DOBJ0 oam_render(gba,screen_line,gba->obj_render[0],0);
/*当执行了一次map渲染时,render_line_ptr就不是第一次渲染了*/
#define DMAP3 RENDER_LAYER(3,3+8,screen_line,render_line);
#define DMAP2 RENDER_LAYER(2,2+8,screen_line,render_line);
#define DMAP1 RENDER_LAYER(1,1+8,screen_line,render_line);
#define DMAP0 RENDER_LAYER(0,0+8,screen_line,render_line);

#define BLEND_DOBJ3 oam_render(gba,obj3_pixel,gba->obj_render[3],3);
#define BLEND_DOBJ2 oam_render(gba,obj2_pixel,gba->obj_render[2],2);
#define BLEND_DOBJ1 oam_render(gba,obj1_pixel,gba->obj_render[1],1);
#define BLEND_DOBJ0 oam_render(gba,obj0_pixel,gba->obj_render[0],0);
#define BLEND_DMAP3 RENDER_LAYER(3,3+8,map3_pixel,render_line);
#define BLEND_DMAP2 RENDER_LAYER(2,2+8,map2_pixel,render_line);
#define BLEND_DMAP1 RENDER_LAYER(1,1+8,map1_pixel,render_line);
#define BLEND_DMAP0 RENDER_LAYER(0,0+8,map0_pixel,render_line);
#define PARAM_DOBJ3 layer[layer_num].num = 4; layer[layer_num++].pixel = obj3_pixel;
#define PARAM_DOBJ2 layer[layer_num].num = 4; layer[layer_num++].pixel = obj2_pixel;
#define PARAM_DOBJ1 layer[layer_num].num = 4; layer[layer_num++].pixel = obj1_pixel;
#define PARAM_DOBJ0 layer[layer_num].num = 4; layer[layer_num++].pixel = obj0_pixel;
#define PARAM_DMAP3 layer[layer_num].num = 3; layer[layer_num++].pixel = map3_pixel;
#define PARAM_DMAP2 layer[layer_num].num = 2; layer[layer_num++].pixel = map2_pixel;
#define PARAM_DMAP1 layer[layer_num].num = 1; layer[layer_num++].pixel = map1_pixel;
#define PARAM_DMAP0 layer[layer_num].num = 0; layer[layer_num++].pixel = map0_pixel;


#define DEF_VRAM_FUNC(name,f1,f2,f3,f4,f5,f6,f7,f8) \
static int tile_render_##name(xgba_t*gba,uint32_t *screen_line){ \
    struct xgba_bgcnt_t *cnt0 = (struct xgba_bgcnt_t*)&gba->io[0x8]; \
    struct xgba_bgcnt_t *cnt1 = (struct xgba_bgcnt_t*)&gba->io[0xA]; \
    struct xgba_bgcnt_t *cnt2 = (struct xgba_bgcnt_t*)&gba->io[0xC]; \
    struct xgba_bgcnt_t *cnt3 = (struct xgba_bgcnt_t*)&gba->io[0xE]; \
    tile_render_line_func_t *render_line_ptr = render_line; \
    f1;\
    f2;\
    f3;\
    f4;\
    f5;\
    f6;\
    f7;\
    f8;\
} \
/*混合*/ \
static int tile_render_##name##blend(xgba_t*gba,uint32_t *screen_line){ \
    struct xgba_bgcnt_t *cnt0 = (struct xgba_bgcnt_t*)&gba->io[0x8]; \
    struct xgba_bgcnt_t *cnt1 = (struct xgba_bgcnt_t*)&gba->io[0xA]; \
    struct xgba_bgcnt_t *cnt2 = (struct xgba_bgcnt_t*)&gba->io[0xC]; \
    struct xgba_bgcnt_t *cnt3 = (struct xgba_bgcnt_t*)&gba->io[0xE]; \
    uint32_t map0_pixel[0x200];      /*512*/ \
    uint32_t map1_pixel[0x200];      /*512*/ \
    uint32_t map2_pixel[0x200];      /*512*/ \
    uint32_t map3_pixel[0x200];      /*512*/ \
    uint32_t obj0_pixel[0x200];      /*512*/ \
    uint32_t obj1_pixel[0x200];      /*512*/ \
    uint32_t obj2_pixel[0x200];      /*512*/ \
    uint32_t obj3_pixel[0x200];      /*512*/ \
    vram_pixel_layer_t layer[8]; \
    int layer_num = 0; \
    memset(map0_pixel,0,sizeof(map0_pixel)); \
    memset(map1_pixel,0,sizeof(map1_pixel)); \
    memset(map2_pixel,0,sizeof(map2_pixel)); \
    memset(map3_pixel,0,sizeof(map3_pixel)); \
    memset(obj0_pixel,0,sizeof(map0_pixel)); \
    memset(obj1_pixel,0,sizeof(map1_pixel)); \
    memset(obj2_pixel,0,sizeof(map2_pixel)); \
    memset(obj3_pixel,0,sizeof(map3_pixel)); \
    BLEND_##f1; /*直接绘制到缓存中*/ \
    BLEND_##f2; /*直接绘制到缓存中*/ \
    BLEND_##f3; /*直接绘制到缓存中*/ \
    BLEND_##f4; /*直接绘制到缓存中*/ \
    BLEND_##f5; /*直接绘制到缓存中*/ \
    BLEND_##f6; /*直接绘制到缓存中*/ \
    BLEND_##f7; /*直接绘制到缓存中*/ \
    BLEND_##f8; /*直接绘制到缓存中*/ \
    PARAM_##f1; \
    PARAM_##f2; \
    PARAM_##f3; \
    PARAM_##f4; \
    PARAM_##f5; \
    PARAM_##f6; \
    PARAM_##f7; \
    PARAM_##f8; \
    pixel_blend(gba,screen_line,layer); \
}

DEF_VRAM_FUNC(0x00,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP2,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x01,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP3,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x02,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP3,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x03,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x04,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP3,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x05,DOBJ3,DOBJ2,DMAP1,DMAP0,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x06,DOBJ3,DMAP0,DOBJ2,DMAP1,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x07,DMAP0,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x08,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP3,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x09,DOBJ3,DMAP1,DOBJ2,DMAP0,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x0A,DOBJ3,DMAP1,DMAP0,DOBJ2,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x0B,DMAP0,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x0C,DMAP1,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x0D,DMAP1,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x0E,DMAP1,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x0F,DMAP1,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x10,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP3,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x11,DOBJ3,DOBJ2,DMAP2,DMAP0,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x12,DOBJ3,DMAP0,DOBJ2,DMAP2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x13,DMAP0,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x14,DOBJ3,DOBJ2,DMAP2,DMAP1,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x15,DOBJ3,DOBJ2,DMAP2,DMAP1,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x16,DOBJ3,DMAP0,DOBJ2,DMAP2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x17,DMAP0,DOBJ3,DOBJ2,DMAP2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x18,DOBJ3,DMAP1,DOBJ2,DMAP2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x19,DOBJ3,DMAP1,DOBJ2,DMAP2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x1A,DOBJ3,DMAP1,DMAP0,DOBJ2,DMAP2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x1B,DMAP0,DOBJ3,DMAP1,DOBJ2,DMAP2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x1C,DMAP1,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x1D,DMAP1,DOBJ3,DOBJ2,DMAP2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x1E,DMAP1,DOBJ3,DMAP0,DOBJ2,DMAP2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x1F,DMAP1,DMAP0,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x20,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP3,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x21,DOBJ3,DMAP2,DOBJ2,DMAP0,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x22,DOBJ3,DMAP2,DMAP0,DOBJ2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x23,DMAP0,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x24,DOBJ3,DMAP2,DOBJ2,DMAP1,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x25,DOBJ3,DMAP2,DOBJ2,DMAP1,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x26,DOBJ3,DMAP2,DMAP0,DOBJ2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x27,DMAP0,DOBJ3,DMAP2,DOBJ2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x28,DOBJ3,DMAP2,DMAP1,DOBJ2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x29,DOBJ3,DMAP2,DMAP1,DOBJ2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x2A,DOBJ3,DMAP2,DMAP1,DMAP0,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x2B,DMAP0,DOBJ3,DMAP2,DMAP1,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x2C,DMAP1,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x2D,DMAP1,DOBJ3,DMAP2,DOBJ2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x2E,DMAP1,DOBJ3,DMAP2,DMAP0,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x2F,DMAP1,DMAP0,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x30,DMAP2,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x31,DMAP2,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x32,DMAP2,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x33,DMAP2,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x34,DMAP2,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x35,DMAP2,DOBJ3,DOBJ2,DMAP1,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x36,DMAP2,DOBJ3,DMAP0,DOBJ2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x37,DMAP2,DMAP0,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x38,DMAP2,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x39,DMAP2,DOBJ3,DMAP1,DOBJ2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x3A,DMAP2,DOBJ3,DMAP1,DMAP0,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x3B,DMAP2,DMAP0,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x3C,DMAP2,DMAP1,DOBJ3,DOBJ2,DOBJ1,DMAP3,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x3D,DMAP2,DMAP1,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x3E,DMAP2,DMAP1,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x3F,DMAP2,DMAP1,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP3,DOBJ0);
DEF_VRAM_FUNC(0x40,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP2,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x41,DOBJ3,DOBJ2,DMAP3,DMAP0,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x42,DOBJ3,DMAP0,DOBJ2,DMAP3,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x43,DMAP0,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x44,DOBJ3,DOBJ2,DMAP3,DMAP1,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x45,DOBJ3,DOBJ2,DMAP3,DMAP1,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x46,DOBJ3,DMAP0,DOBJ2,DMAP3,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x47,DMAP0,DOBJ3,DOBJ2,DMAP3,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x48,DOBJ3,DMAP1,DOBJ2,DMAP3,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x49,DOBJ3,DMAP1,DOBJ2,DMAP3,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x4A,DOBJ3,DMAP1,DMAP0,DOBJ2,DMAP3,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x4B,DMAP0,DOBJ3,DMAP1,DOBJ2,DMAP3,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x4C,DMAP1,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x4D,DMAP1,DOBJ3,DOBJ2,DMAP3,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x4E,DMAP1,DOBJ3,DMAP0,DOBJ2,DMAP3,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x4F,DMAP1,DMAP0,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x50,DOBJ3,DOBJ2,DMAP3,DMAP2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x51,DOBJ3,DOBJ2,DMAP3,DMAP2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x52,DOBJ3,DMAP0,DOBJ2,DMAP3,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x53,DMAP0,DOBJ3,DOBJ2,DMAP3,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x54,DOBJ3,DOBJ2,DMAP3,DMAP2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x55,DOBJ3,DOBJ2,DMAP3,DMAP2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x56,DOBJ3,DMAP0,DOBJ2,DMAP3,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x57,DMAP0,DOBJ3,DOBJ2,DMAP3,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x58,DOBJ3,DMAP1,DOBJ2,DMAP3,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x59,DOBJ3,DMAP1,DOBJ2,DMAP3,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x5A,DOBJ3,DMAP1,DMAP0,DOBJ2,DMAP3,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x5B,DMAP0,DOBJ3,DMAP1,DOBJ2,DMAP3,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x5C,DMAP1,DOBJ3,DOBJ2,DMAP3,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x5D,DMAP1,DOBJ3,DOBJ2,DMAP3,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x5E,DMAP1,DOBJ3,DMAP0,DOBJ2,DMAP3,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x5F,DMAP1,DMAP0,DOBJ3,DOBJ2,DMAP3,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x60,DOBJ3,DMAP2,DOBJ2,DMAP3,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x61,DOBJ3,DMAP2,DOBJ2,DMAP3,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x62,DOBJ3,DMAP2,DMAP0,DOBJ2,DMAP3,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x63,DMAP0,DOBJ3,DMAP2,DOBJ2,DMAP3,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x64,DOBJ3,DMAP2,DOBJ2,DMAP3,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x65,DOBJ3,DMAP2,DOBJ2,DMAP3,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x66,DOBJ3,DMAP2,DMAP0,DOBJ2,DMAP3,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x67,DMAP0,DOBJ3,DMAP2,DOBJ2,DMAP3,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x68,DOBJ3,DMAP2,DMAP1,DOBJ2,DMAP3,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x69,DOBJ3,DMAP2,DMAP1,DOBJ2,DMAP3,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x6A,DOBJ3,DMAP2,DMAP1,DMAP0,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x6B,DMAP0,DOBJ3,DMAP2,DMAP1,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x6C,DMAP1,DOBJ3,DMAP2,DOBJ2,DMAP3,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x6D,DMAP1,DOBJ3,DMAP2,DOBJ2,DMAP3,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x6E,DMAP1,DOBJ3,DMAP2,DMAP0,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x6F,DMAP1,DMAP0,DOBJ3,DMAP2,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x70,DMAP2,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x71,DMAP2,DOBJ3,DOBJ2,DMAP3,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x72,DMAP2,DOBJ3,DMAP0,DOBJ2,DMAP3,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x73,DMAP2,DMAP0,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x74,DMAP2,DOBJ3,DOBJ2,DMAP3,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x75,DMAP2,DOBJ3,DOBJ2,DMAP3,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x76,DMAP2,DOBJ3,DMAP0,DOBJ2,DMAP3,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x77,DMAP2,DMAP0,DOBJ3,DOBJ2,DMAP3,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x78,DMAP2,DOBJ3,DMAP1,DOBJ2,DMAP3,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x79,DMAP2,DOBJ3,DMAP1,DOBJ2,DMAP3,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x7A,DMAP2,DOBJ3,DMAP1,DMAP0,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x7B,DMAP2,DMAP0,DOBJ3,DMAP1,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x7C,DMAP2,DMAP1,DOBJ3,DOBJ2,DMAP3,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x7D,DMAP2,DMAP1,DOBJ3,DOBJ2,DMAP3,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x7E,DMAP2,DMAP1,DOBJ3,DMAP0,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x7F,DMAP2,DMAP1,DMAP0,DOBJ3,DOBJ2,DMAP3,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x80,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP2,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x81,DOBJ3,DMAP3,DOBJ2,DMAP0,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x82,DOBJ3,DMAP3,DMAP0,DOBJ2,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x83,DMAP0,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x84,DOBJ3,DMAP3,DOBJ2,DMAP1,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x85,DOBJ3,DMAP3,DOBJ2,DMAP1,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x86,DOBJ3,DMAP3,DMAP0,DOBJ2,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x87,DMAP0,DOBJ3,DMAP3,DOBJ2,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x88,DOBJ3,DMAP3,DMAP1,DOBJ2,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x89,DOBJ3,DMAP3,DMAP1,DOBJ2,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x8A,DOBJ3,DMAP3,DMAP1,DMAP0,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x8B,DMAP0,DOBJ3,DMAP3,DMAP1,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x8C,DMAP1,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x8D,DMAP1,DOBJ3,DMAP3,DOBJ2,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x8E,DMAP1,DOBJ3,DMAP3,DMAP0,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x8F,DMAP1,DMAP0,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0x90,DOBJ3,DMAP3,DOBJ2,DMAP2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x91,DOBJ3,DMAP3,DOBJ2,DMAP2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x92,DOBJ3,DMAP3,DMAP0,DOBJ2,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x93,DMAP0,DOBJ3,DMAP3,DOBJ2,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0x94,DOBJ3,DMAP3,DOBJ2,DMAP2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x95,DOBJ3,DMAP3,DOBJ2,DMAP2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x96,DOBJ3,DMAP3,DMAP0,DOBJ2,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x97,DMAP0,DOBJ3,DMAP3,DOBJ2,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x98,DOBJ3,DMAP3,DMAP1,DOBJ2,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x99,DOBJ3,DMAP3,DMAP1,DOBJ2,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x9A,DOBJ3,DMAP3,DMAP1,DMAP0,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x9B,DMAP0,DOBJ3,DMAP3,DMAP1,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x9C,DMAP1,DOBJ3,DMAP3,DOBJ2,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0x9D,DMAP1,DOBJ3,DMAP3,DOBJ2,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x9E,DMAP1,DOBJ3,DMAP3,DMAP0,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0x9F,DMAP1,DMAP0,DOBJ3,DMAP3,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xA0,DOBJ3,DMAP3,DMAP2,DOBJ2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xA1,DOBJ3,DMAP3,DMAP2,DOBJ2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xA2,DOBJ3,DMAP3,DMAP2,DMAP0,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xA3,DMAP0,DOBJ3,DMAP3,DMAP2,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xA4,DOBJ3,DMAP3,DMAP2,DOBJ2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xA5,DOBJ3,DMAP3,DMAP2,DOBJ2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xA6,DOBJ3,DMAP3,DMAP2,DMAP0,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xA7,DMAP0,DOBJ3,DMAP3,DMAP2,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xA8,DOBJ3,DMAP3,DMAP2,DMAP1,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xA9,DOBJ3,DMAP3,DMAP2,DMAP1,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xAA,DOBJ3,DMAP3,DMAP2,DMAP1,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xAB,DMAP0,DOBJ3,DMAP3,DMAP2,DMAP1,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xAC,DMAP1,DOBJ3,DMAP3,DMAP2,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xAD,DMAP1,DOBJ3,DMAP3,DMAP2,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xAE,DMAP1,DOBJ3,DMAP3,DMAP2,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xAF,DMAP1,DMAP0,DOBJ3,DMAP3,DMAP2,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xB0,DMAP2,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xB1,DMAP2,DOBJ3,DMAP3,DOBJ2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xB2,DMAP2,DOBJ3,DMAP3,DMAP0,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xB3,DMAP2,DMAP0,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xB4,DMAP2,DOBJ3,DMAP3,DOBJ2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xB5,DMAP2,DOBJ3,DMAP3,DOBJ2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xB6,DMAP2,DOBJ3,DMAP3,DMAP0,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xB7,DMAP2,DMAP0,DOBJ3,DMAP3,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xB8,DMAP2,DOBJ3,DMAP3,DMAP1,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xB9,DMAP2,DOBJ3,DMAP3,DMAP1,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xBA,DMAP2,DOBJ3,DMAP3,DMAP1,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xBB,DMAP2,DMAP0,DOBJ3,DMAP3,DMAP1,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xBC,DMAP2,DMAP1,DOBJ3,DMAP3,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xBD,DMAP2,DMAP1,DOBJ3,DMAP3,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xBE,DMAP2,DMAP1,DOBJ3,DMAP3,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xBF,DMAP2,DMAP1,DMAP0,DOBJ3,DMAP3,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xC0,DMAP3,DOBJ3,DOBJ2,DOBJ1,DMAP2,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xC1,DMAP3,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xC2,DMAP3,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xC3,DMAP3,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP2,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xC4,DMAP3,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xC5,DMAP3,DOBJ3,DOBJ2,DMAP1,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xC6,DMAP3,DOBJ3,DMAP0,DOBJ2,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xC7,DMAP3,DMAP0,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xC8,DMAP3,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xC9,DMAP3,DOBJ3,DMAP1,DOBJ2,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xCA,DMAP3,DOBJ3,DMAP1,DMAP0,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xCB,DMAP3,DMAP0,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xCC,DMAP3,DMAP1,DOBJ3,DOBJ2,DOBJ1,DMAP2,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xCD,DMAP3,DMAP1,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xCE,DMAP3,DMAP1,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xCF,DMAP3,DMAP1,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP2,DOBJ0);
DEF_VRAM_FUNC(0xD0,DMAP3,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xD1,DMAP3,DOBJ3,DOBJ2,DMAP2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xD2,DMAP3,DOBJ3,DMAP0,DOBJ2,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xD3,DMAP3,DMAP0,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xD4,DMAP3,DOBJ3,DOBJ2,DMAP2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xD5,DMAP3,DOBJ3,DOBJ2,DMAP2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xD6,DMAP3,DOBJ3,DMAP0,DOBJ2,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xD7,DMAP3,DMAP0,DOBJ3,DOBJ2,DMAP2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xD8,DMAP3,DOBJ3,DMAP1,DOBJ2,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xD9,DMAP3,DOBJ3,DMAP1,DOBJ2,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xDA,DMAP3,DOBJ3,DMAP1,DMAP0,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xDB,DMAP3,DMAP0,DOBJ3,DMAP1,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xDC,DMAP3,DMAP1,DOBJ3,DOBJ2,DMAP2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xDD,DMAP3,DMAP1,DOBJ3,DOBJ2,DMAP2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xDE,DMAP3,DMAP1,DOBJ3,DMAP0,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xDF,DMAP3,DMAP1,DMAP0,DOBJ3,DOBJ2,DMAP2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xE0,DMAP3,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xE1,DMAP3,DOBJ3,DMAP2,DOBJ2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xE2,DMAP3,DOBJ3,DMAP2,DMAP0,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xE3,DMAP3,DMAP0,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xE4,DMAP3,DOBJ3,DMAP2,DOBJ2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xE5,DMAP3,DOBJ3,DMAP2,DOBJ2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xE6,DMAP3,DOBJ3,DMAP2,DMAP0,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xE7,DMAP3,DMAP0,DOBJ3,DMAP2,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xE8,DMAP3,DOBJ3,DMAP2,DMAP1,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xE9,DMAP3,DOBJ3,DMAP2,DMAP1,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xEA,DMAP3,DOBJ3,DMAP2,DMAP1,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xEB,DMAP3,DMAP0,DOBJ3,DMAP2,DMAP1,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xEC,DMAP3,DMAP1,DOBJ3,DMAP2,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xED,DMAP3,DMAP1,DOBJ3,DMAP2,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xEE,DMAP3,DMAP1,DOBJ3,DMAP2,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xEF,DMAP3,DMAP1,DMAP0,DOBJ3,DMAP2,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xF0,DMAP3,DMAP2,DOBJ3,DOBJ2,DOBJ1,DMAP1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xF1,DMAP3,DMAP2,DOBJ3,DOBJ2,DMAP0,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xF2,DMAP3,DMAP2,DOBJ3,DMAP0,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xF3,DMAP3,DMAP2,DMAP0,DOBJ3,DOBJ2,DOBJ1,DMAP1,DOBJ0);
DEF_VRAM_FUNC(0xF4,DMAP3,DMAP2,DOBJ3,DOBJ2,DMAP1,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xF5,DMAP3,DMAP2,DOBJ3,DOBJ2,DMAP1,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xF6,DMAP3,DMAP2,DOBJ3,DMAP0,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xF7,DMAP3,DMAP2,DMAP0,DOBJ3,DOBJ2,DMAP1,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xF8,DMAP3,DMAP2,DOBJ3,DMAP1,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xF9,DMAP3,DMAP2,DOBJ3,DMAP1,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xFA,DMAP3,DMAP2,DOBJ3,DMAP1,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xFB,DMAP3,DMAP2,DMAP0,DOBJ3,DMAP1,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xFC,DMAP3,DMAP2,DMAP1,DOBJ3,DOBJ2,DOBJ1,DMAP0,DOBJ0);
DEF_VRAM_FUNC(0xFD,DMAP3,DMAP2,DMAP1,DOBJ3,DOBJ2,DMAP0,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xFE,DMAP3,DMAP2,DMAP1,DOBJ3,DMAP0,DOBJ2,DOBJ1,DOBJ0);
DEF_VRAM_FUNC(0xFF,DMAP3,DMAP2,DMAP1,DMAP0,DOBJ3,DOBJ2,DOBJ1,DOBJ0);

static int tile_render_init(xgba_t*gba){

     /*
    查看各个区域存在多少个渲染图层
    0~3     :渲染优先级为0的图层数
    4~7     :渲染优先级为1的图层数
    8~11    :渲染优先级为2的图层数
    12~15   :渲染优先级为3的图层数
    */
    #define SET_PRIO(v,f) \
        /* gba->tile_render[v] = tile_render_##f; */ \
    { \
        int p = 0; \
        /*p0,p1,p2,p3图层优先权*/ \
        int p0 = (v>>0)&0x3; \
        int p1 = (v>>2)&0x3; \
        int p2 = (v>>4)&0x3; \
        int p3 = (v>>6)&0x3; \
        p += 1<<(p0*8); \
        p += 1<<(p1*8); \
        p += 1<<(p2*8); \
        p += 1<<(p3*8); \
        int pi = 0; \
        pi += (p>>0)&0xf; \
        gba->obj_prio[v] = pi&0xf; /*优先级为0的渲染图层数*/ \
        pi += (p>>4)&0xf; \
        gba->obj_prio[v] = pi&0xf; /*优先级为1的渲染图层数*/ \
        pi += (p>>8)&0xf; \
        gba->obj_prio[v] = pi&0xf; /*优先级为2的渲染图层数*/ \
        pi += (p>>12)&0xf; \
        gba->obj_prio[v] = pi&0xf; /*优先级为3的渲染图层数*/ \
        gba->tile_render[v] = tile_render_##f; \
    }

    #undef SET_PRIO
    #define SET_PRIO(value,...) \
        gba->tile_render[value] = tile_render_##value; \
        gba->tile_render_blend[value] = tile_render_##value##blend;

    SET_PRIO(0x00,m0_m1_m2_m3)
    SET_PRIO(0x01,m1_m2_m3_m0)
    SET_PRIO(0x02,m1_m2_m3_m0)
    SET_PRIO(0x03,m1_m2_m3_m0)
    SET_PRIO(0x04,m0_m2_m3_m1)
    SET_PRIO(0x05,m2_m3_m0_m1)
    SET_PRIO(0x06,m2_m3_m1_m0)
    SET_PRIO(0x07,m2_m3_m1_m0)
    SET_PRIO(0x08,m0_m2_m3_m1)
    SET_PRIO(0x09,m2_m3_m0_m1)
    SET_PRIO(0x0A,m2_m3_m0_m1)
    SET_PRIO(0x0B,m2_m3_m1_m0)
    SET_PRIO(0x0C,m0_m2_m3_m1)
    SET_PRIO(0x0D,m2_m3_m0_m1)
    SET_PRIO(0x0E,m2_m3_m0_m1)
    SET_PRIO(0x0F,m2_m3_m0_m1)
    SET_PRIO(0x10,m0_m1_m3_m2)
    SET_PRIO(0x11,m1_m3_m0_m2)
    SET_PRIO(0x12,m1_m3_m2_m0)
    SET_PRIO(0x13,m1_m3_m2_m0)
    SET_PRIO(0x14,m0_m3_m1_m2)
    SET_PRIO(0x15,m3_m0_m1_m2)
    SET_PRIO(0x16,m3_m1_m2_m0)
    SET_PRIO(0x17,m3_m1_m2_m0)
    SET_PRIO(0x18,m0_m3_m2_m1)
    SET_PRIO(0x19,m3_m0_m2_m1)
    SET_PRIO(0x1A,m3_m2_m0_m1)
    SET_PRIO(0x1B,m3_m2_m1_m0)
    SET_PRIO(0x1C,m0_m3_m2_m1)
    SET_PRIO(0x1D,m3_m0_m2_m1)
    SET_PRIO(0x1E,m3_m2_m0_m1)
    SET_PRIO(0x1F,m3_m2_m0_m1)
    SET_PRIO(0x20,m0_m1_m3_m2)
    SET_PRIO(0x21,m1_m3_m0_m2)
    SET_PRIO(0x22,m1_m3_m0_m2)
    SET_PRIO(0x23,m1_m3_m2_m0)
    SET_PRIO(0x24,m0_m3_m1_m2)
    SET_PRIO(0x25,m3_m0_m1_m2)
    SET_PRIO(0x26,m3_m1_m0_m2)
    SET_PRIO(0x27,m3_m1_m2_m0)
    SET_PRIO(0x28,m0_m3_m1_m2)
    SET_PRIO(0x29,m3_m0_m1_m2)
    SET_PRIO(0x2A,m3_m0_m1_m2)
    SET_PRIO(0x2B,m3_m1_m2_m0)
    SET_PRIO(0x2C,m0_m3_m2_m1)
    SET_PRIO(0x2D,m3_m0_m2_m1)
    SET_PRIO(0x2E,m3_m0_m2_m1)
    SET_PRIO(0x2F,m3_m2_m0_m1)
    SET_PRIO(0x30,m0_m1_m3_m2)
    SET_PRIO(0x31,m1_m3_m0_m2)
    SET_PRIO(0x32,m1_m3_m0_m2)
    SET_PRIO(0x33,m1_m3_m0_m2)
    SET_PRIO(0x34,m0_m3_m1_m2)
    SET_PRIO(0x35,m3_m0_m1_m2)
    SET_PRIO(0x36,m3_m1_m0_m2)
    SET_PRIO(0x37,m3_m1_m0_m2)
    SET_PRIO(0x38,m0_m3_m1_m2)
    SET_PRIO(0x39,m3_m0_m1_m2)
    SET_PRIO(0x3A,m3_m0_m1_m2)
    SET_PRIO(0x3B,m3_m1_m0_m2)
    SET_PRIO(0x3C,m0_m3_m1_m2)
    SET_PRIO(0x3D,m3_m0_m1_m2)
    SET_PRIO(0x3E,m3_m0_m1_m2)
    SET_PRIO(0x3F,m3_m0_m1_m2)
    SET_PRIO(0x40,m0_m1_m2_m3)
    SET_PRIO(0x41,m1_m2_m0_m3)
    SET_PRIO(0x42,m1_m2_m3_m0)
    SET_PRIO(0x43,m1_m2_m3_m0)
    SET_PRIO(0x44,m0_m2_m1_m3)
    SET_PRIO(0x45,m2_m0_m1_m3)
    SET_PRIO(0x46,m2_m1_m3_m0)
    SET_PRIO(0x47,m2_m1_m3_m0)
    SET_PRIO(0x48,m0_m2_m3_m1)
    SET_PRIO(0x49,m2_m0_m3_m1)
    SET_PRIO(0x4A,m2_m3_m0_m1)
    SET_PRIO(0x4B,m2_m3_m1_m0)
    SET_PRIO(0x4C,m0_m2_m3_m1)
    SET_PRIO(0x4D,m2_m0_m3_m1)
    SET_PRIO(0x4E,m2_m3_m0_m1)
    SET_PRIO(0x4F,m2_m3_m0_m1)
    SET_PRIO(0x50,m0_m1_m2_m3)
    SET_PRIO(0x51,m1_m0_m2_m3)
    SET_PRIO(0x52,m1_m2_m3_m0)
    SET_PRIO(0x53,m1_m2_m3_m0)
    SET_PRIO(0x54,m0_m1_m2_m3)
    SET_PRIO(0x55,m0_m1_m2_m3)
    SET_PRIO(0x56,m1_m2_m3_m0)
    SET_PRIO(0x57,m1_m2_m3_m0)
    SET_PRIO(0x58,m0_m2_m3_m1)
    SET_PRIO(0x59,m0_m2_m3_m1)
    SET_PRIO(0x5A,m2_m3_m0_m1)
    SET_PRIO(0x5B,m2_m3_m1_m0)
    SET_PRIO(0x5C,m0_m2_m3_m1)
    SET_PRIO(0x5D,m0_m2_m3_m1)
    SET_PRIO(0x5E,m2_m3_m0_m1)
    SET_PRIO(0x5F,m2_m3_m0_m1)
    SET_PRIO(0x60,m0_m1_m3_m2)
    SET_PRIO(0x61,m1_m0_m3_m2)
    SET_PRIO(0x62,m1_m3_m0_m2)
    SET_PRIO(0x63,m1_m3_m2_m0)
    SET_PRIO(0x64,m0_m1_m3_m2)
    SET_PRIO(0x65,m0_m1_m3_m2)
    SET_PRIO(0x66,m1_m3_m0_m2)
    SET_PRIO(0x67,m1_m3_m2_m0)
    SET_PRIO(0x68,m0_m3_m1_m2)
    SET_PRIO(0x69,m0_m3_m1_m2)
    SET_PRIO(0x6A,m3_m0_m1_m2)
    SET_PRIO(0x6B,m3_m1_m2_m0)
    SET_PRIO(0x6C,m0_m3_m2_m1)
    SET_PRIO(0x6D,m0_m3_m2_m1)
    SET_PRIO(0x6E,m3_m0_m2_m1)
    SET_PRIO(0x6F,m3_m2_m0_m1)
    SET_PRIO(0x70,m0_m1_m3_m2)
    SET_PRIO(0x71,m1_m0_m3_m2)
    SET_PRIO(0x72,m1_m3_m0_m2)
    SET_PRIO(0x73,m1_m3_m0_m2)
    SET_PRIO(0x74,m0_m1_m3_m2)
    SET_PRIO(0x75,m0_m1_m3_m2)
    SET_PRIO(0x76,m1_m3_m0_m2)
    SET_PRIO(0x77,m1_m3_m0_m2)
    SET_PRIO(0x78,m0_m3_m1_m2)
    SET_PRIO(0x79,m0_m3_m1_m2)
    SET_PRIO(0x7A,m3_m0_m1_m2)
    SET_PRIO(0x7B,m3_m1_m0_m2)
    SET_PRIO(0x7C,m0_m3_m1_m2)
    SET_PRIO(0x7D,m0_m3_m1_m2)
    SET_PRIO(0x7E,m3_m0_m1_m2)
    SET_PRIO(0x7F,m3_m0_m1_m2)
    SET_PRIO(0x80,m0_m1_m2_m3)
    SET_PRIO(0x81,m1_m2_m0_m3)
    SET_PRIO(0x82,m1_m2_m0_m3)
    SET_PRIO(0x83,m1_m2_m3_m0)
    SET_PRIO(0x84,m0_m2_m1_m3)
    SET_PRIO(0x85,m2_m0_m1_m3)
    SET_PRIO(0x86,m2_m1_m0_m3)
    SET_PRIO(0x87,m2_m1_m3_m0)
    SET_PRIO(0x88,m0_m2_m1_m3)
    SET_PRIO(0x89,m2_m0_m1_m3)
    SET_PRIO(0x8A,m2_m0_m1_m3)
    SET_PRIO(0x8B,m2_m1_m3_m0)
    SET_PRIO(0x8C,m0_m2_m3_m1)
    SET_PRIO(0x8D,m2_m0_m3_m1)
    SET_PRIO(0x8E,m2_m0_m3_m1)
    SET_PRIO(0x8F,m2_m3_m0_m1)
    SET_PRIO(0x90,m0_m1_m2_m3)
    SET_PRIO(0x91,m1_m0_m2_m3)
    SET_PRIO(0x92,m1_m2_m0_m3)
    SET_PRIO(0x93,m1_m2_m3_m0)
    SET_PRIO(0x94,m0_m1_m2_m3)
    SET_PRIO(0x95,m0_m1_m2_m3)
    SET_PRIO(0x96,m1_m2_m0_m3)
    SET_PRIO(0x97,m1_m2_m3_m0)
    SET_PRIO(0x98,m0_m2_m1_m3)
    SET_PRIO(0x99,m0_m2_m1_m3)
    SET_PRIO(0x9A,m2_m0_m1_m3)
    SET_PRIO(0x9B,m2_m1_m3_m0)
    SET_PRIO(0x9C,m0_m2_m3_m1)
    SET_PRIO(0x9D,m0_m2_m3_m1)
    SET_PRIO(0x9E,m2_m0_m3_m1)
    SET_PRIO(0x9F,m2_m3_m0_m1)
    SET_PRIO(0xA0,m0_m1_m2_m3)
    SET_PRIO(0xA1,m1_m0_m2_m3)
    SET_PRIO(0xA2,m1_m0_m2_m3)
    SET_PRIO(0xA3,m1_m2_m3_m0)
    SET_PRIO(0xA4,m0_m1_m2_m3)
    SET_PRIO(0xA5,m0_m1_m2_m3)
    SET_PRIO(0xA6,m1_m0_m2_m3)
    SET_PRIO(0xA7,m1_m2_m3_m0)
    SET_PRIO(0xA8,m0_m1_m2_m3)
    SET_PRIO(0xA9,m0_m1_m2_m3)
    SET_PRIO(0xAA,m0_m1_m2_m3)
    SET_PRIO(0xAB,m1_m2_m3_m0)
    SET_PRIO(0xAC,m0_m2_m3_m1)
    SET_PRIO(0xAD,m0_m2_m3_m1)
    SET_PRIO(0xAE,m0_m2_m3_m1)
    SET_PRIO(0xAF,m2_m3_m0_m1)
    SET_PRIO(0xB0,m0_m1_m3_m2)
    SET_PRIO(0xB1,m1_m0_m3_m2)
    SET_PRIO(0xB2,m1_m0_m3_m2)
    SET_PRIO(0xB3,m1_m3_m0_m2)
    SET_PRIO(0xB4,m0_m1_m3_m2)
    SET_PRIO(0xB5,m0_m1_m3_m2)
    SET_PRIO(0xB6,m1_m0_m3_m2)
    SET_PRIO(0xB7,m1_m3_m0_m2)
    SET_PRIO(0xB8,m0_m1_m3_m2)
    SET_PRIO(0xB9,m0_m1_m3_m2)
    SET_PRIO(0xBA,m0_m1_m3_m2)
    SET_PRIO(0xBB,m1_m3_m0_m2)
    SET_PRIO(0xBC,m0_m3_m1_m2)
    SET_PRIO(0xBD,m0_m3_m1_m2)
    SET_PRIO(0xBE,m0_m3_m1_m2)
    SET_PRIO(0xBF,m3_m0_m1_m2)
    SET_PRIO(0xC0,m0_m1_m2_m3)
    SET_PRIO(0xC1,m1_m2_m0_m3)
    SET_PRIO(0xC2,m1_m2_m0_m3)
    SET_PRIO(0xC3,m1_m2_m0_m3)
    SET_PRIO(0xC4,m0_m2_m1_m3)
    SET_PRIO(0xC5,m2_m0_m1_m3)
    SET_PRIO(0xC6,m2_m1_m0_m3)
    SET_PRIO(0xC7,m2_m1_m0_m3)
    SET_PRIO(0xC8,m0_m2_m1_m3)
    SET_PRIO(0xC9,m2_m0_m1_m3)
    SET_PRIO(0xCA,m2_m0_m1_m3)
    SET_PRIO(0xCB,m2_m1_m0_m3)
    SET_PRIO(0xCC,m0_m2_m1_m3)
    SET_PRIO(0xCD,m2_m0_m1_m3)
    SET_PRIO(0xCE,m2_m0_m1_m3)
    SET_PRIO(0xCF,m2_m0_m1_m3)
    SET_PRIO(0xD0,m0_m1_m2_m3)
    SET_PRIO(0xD1,m1_m0_m2_m3)
    SET_PRIO(0xD2,m1_m2_m0_m3)
    SET_PRIO(0xD3,m1_m2_m0_m3)
    SET_PRIO(0xD4,m0_m1_m2_m3)
    SET_PRIO(0xD5,m0_m1_m2_m3)
    SET_PRIO(0xD6,m1_m2_m0_m3)
    SET_PRIO(0xD7,m1_m2_m0_m3)
    SET_PRIO(0xD8,m0_m2_m1_m3)
    SET_PRIO(0xD9,m0_m2_m1_m3)
    SET_PRIO(0xDA,m2_m0_m1_m3)
    SET_PRIO(0xDB,m2_m1_m0_m3)
    SET_PRIO(0xDC,m0_m2_m1_m3)
    SET_PRIO(0xDD,m0_m2_m1_m3)
    SET_PRIO(0xDE,m2_m0_m1_m3)
    SET_PRIO(0xDF,m2_m0_m1_m3)
    SET_PRIO(0xE0,m0_m1_m2_m3)
    SET_PRIO(0xE1,m1_m0_m2_m3)
    SET_PRIO(0xE2,m1_m0_m2_m3)
    SET_PRIO(0xE3,m1_m2_m0_m3)
    SET_PRIO(0xE4,m0_m1_m2_m3)
    SET_PRIO(0xE5,m0_m1_m2_m3)
    SET_PRIO(0xE6,m1_m0_m2_m3)
    SET_PRIO(0xE7,m1_m2_m0_m3)
    SET_PRIO(0xE8,m0_m1_m2_m3)
    SET_PRIO(0xE9,m0_m1_m2_m3)
    SET_PRIO(0xEA,m0_m1_m2_m3)
    SET_PRIO(0xEB,m1_m2_m0_m3)
    SET_PRIO(0xEC,m0_m2_m1_m3)
    SET_PRIO(0xED,m0_m2_m1_m3)
    SET_PRIO(0xEE,m0_m2_m1_m3)
    SET_PRIO(0xEF,m2_m0_m1_m3)
    SET_PRIO(0xF0,m0_m1_m2_m3)
    SET_PRIO(0xF1,m1_m0_m2_m3)
    SET_PRIO(0xF2,m1_m0_m2_m3)
    SET_PRIO(0xF3,m1_m0_m2_m3)
    SET_PRIO(0xF4,m0_m1_m2_m3)
    SET_PRIO(0xF5,m0_m1_m2_m3)
    SET_PRIO(0xF6,m1_m0_m2_m3)
    SET_PRIO(0xF7,m1_m0_m2_m3)
    SET_PRIO(0xF8,m0_m1_m2_m3)
    SET_PRIO(0xF9,m0_m1_m2_m3)
    SET_PRIO(0xFA,m0_m1_m2_m3)
    SET_PRIO(0xFB,m1_m0_m2_m3)
    SET_PRIO(0xFC,m0_m1_m2_m3)
    SET_PRIO(0xFD,m0_m1_m2_m3)
    SET_PRIO(0xFE,m0_m1_m2_m3)
    SET_PRIO(0xFF,m0_m1_m2_m3)
}


int xgba_vram_init(xgba_t*gba){
    return tile_render_init(gba);
}

static void proc_pal(xgba_t*gba){
    int i=0;
    uint16_t *pal = (uint16_t*)gba->pal;
    uint32_t *pal32 = gba->tilePal;
    for(i=0;i<0x200;i++){
        uint32_t r = pal[i]&0x1f;
        uint32_t g = (pal[i]>>5)&0x1f;
        uint32_t b = (pal[i]>>10)&0x1f;
        r<<= 3;
        g<<= 3;
        b<<= 3;
        pal32[i] = (r<<0)|(g<<8)|(b<<16)|(0xff<<24);
    }
}

int xgba_vram_render(xgba_t*gba){
    if(gba->screen_line>=160) return 1;
    proc_pal(gba);
    int prio = gba->io[0x8]&3;      //优先级
    prio |= (gba->io[0xA]&3) <<2;
    prio |= (gba->io[0xC]&3) <<4;
    prio |= (gba->io[0xE]&3) <<6;

    /*
    处理oam优先级
    */
    uint8_t *oam = gba->oam;
    int off = 0;
    int idx = 0;
    int obj_num = 0;

    uint32_t pr = gba->obj_prio[prio];  //对应每个图层的优先级
    gba->obj_render[0][0] = 0;
    gba->obj_render[1][0] = 0;
    gba->obj_render[2][0] = 0;
    gba->obj_render[3][0] = 0;
    if(gba->io[0x1]&0x10){
        for(off=0;off<128*8;off+=8){
            xgba_obj_att0_t *oam0 = (xgba_obj_att0_t*)(oam+off);
            xgba_obj_att1_t *oam1 = (xgba_obj_att1_t*)(oam+off+2);
            xgba_obj_att2_t *oam2 = (xgba_obj_att2_t*)(oam+off+4);
            if(
                oam0->y < 160&&
                oam1->x < 240
            ){
                uint8_t *o_layer = gba->obj_render[oam2->prio];
                int i = o_layer[0];
                o_layer[i+1] = off>>3;
                o_layer[0] = i+1;
            }
        }
    }


    /*
    处理tile优先级
    */
    xgba_tile_render_func_t func = gba->tile_render[prio];
    if((gba->io[0x50]>>6)==0b01){
        func = gba->tile_render_blend[prio];
    }
    if(gba->screen_line==0){
        for(idx=0;idx<240*160;idx++){
            gba->screen[0][idx] = gba->tilePal[0];
        }
    }
    //gba->io[0x1] &= ~0xf;
    func(gba,gba->screen[gba->screen_line]);
}
